package com.xgy.vue_role_system.config.security;


import com.xgy.vue_role_system.config.security.filter.CheckTokenFilter;
import com.xgy.vue_role_system.config.security.handler.AnonymousAuthenticationHandler;
import com.xgy.vue_role_system.config.security.handler.CustomerAccessDeniedHandler;
import com.xgy.vue_role_system.config.security.handler.LoginFailureHandler;
import com.xgy.vue_role_system.config.security.handler.LoginSuccessHandler;
import com.xgy.vue_role_system.config.security.service.CustomerUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * 编写Spring Security配置类
 */
@Configuration
@EnableWebSecurity   //开启Security
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;

    @Autowired
    private CustomerAccessDeniedHandler accessDeniedHandler;

    @Autowired
    private CustomerUserDetailsService customerUserDetailsService;

    @Autowired
    private CheckTokenFilter checkTokenFilter;

    /**
     * 注入密码加密类
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //处理登录认证
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        //在登录之前token过滤器
        http.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class);

        
        //登录过程处理
        http.formLogin()            //表单登录
                .loginProcessingUrl("/api/user/login")  //自定义登录url访问security的默认登录表单，若自己有了登录页后，就不用这个了，可以直接访问controller地址
                .usernameParameter("username")          //配置表单用户名属性，默认是username
                .successHandler(loginSuccessHandler)    //配置认证成功处理器
                .failureHandler(loginFailureHandler)    //配置认证失败处理器
                .and()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //不创建session
                .and()
                .authorizeRequests()                    //设置需要拦截的请求
                .antMatchers("/api/user/login").permitAll()   //登录请求放行
                .anyRequest().authenticated()           //其他请求都需要进行身份认证
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(anonymousAuthenticationHandler)    //配置匿名无权限访问处理器
                .accessDeniedHandler(accessDeniedHandler)         //配置认证用户无权限访问处理器
                .and()
                .cors();    //支持跨域请求
    }


    //配置自己的认证处理方法，并给密码加密
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customerUserDetailsService).passwordEncoder(passwordEncoder());
    }
}
